/**
 * @class   wosh::WoshKernel
 * @brief   The Core of a generic WOSH application. Manage life-cycle of CoreModules.
 *
 * Kernel instance is also the owner of the main wosh::Bus of the system (wosh.Bus.Core).
 *        
 *
 * \image html diagrams/WoshKernel.png "wosh::WoshKernel UML diagram"
 *      
 *
 * @ingroup CoreModules
 ****************************************************************************
 * @version 0.8.013 $Id: WoshKernel.h 2827 2010-08-02 11:01:48Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/*! \page page_core
 * \htmlonly <hr/> \endhtmlonly
 * \section page_core_kernel Kernel
 *
 * wosh::WoshKernel allocates and destroys the core modules.
 *
 * wosh::WoshKernel is a singleton component, required by any \ref page_applications
 * and should be allocated within main entry-point (see \ref woshsrv.cpp "woshsrv's source code").
 *
 * \code
int main(int argc, char **argv)
 {
	Settings* woshSettings = new Settings();
	woshSettings->loadFromArgs(argc, argv);
	std::string woshName = woshSettings->getValueOf( "WoshKernel", "Name", "" ).toString();

	WoshKernel core( woshName, woshSettings );
	core.init();
	core.start();
	core.enterLoop();
	return 0;
 }

 * \endcode
 *
 * @see     \ref CoreModules, wosh::WoshModule
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_WoshKernel_H__
 #define __WOSH_Core_WoshKernel_H__

#include <woshDefs.h>
#include <core/Object.h>
#include <core/Fact.h>
#include <core/Method.h>
#include <core/LogContext.h>
#include <core/BusConnector.h>
#include <core/PropertiesProvider.h>
#include <core/MethodsProvider.h>
#include <core/Settings.h>
#include <core/WoshModule.h>

namespace wosh {

 // Core-Modules
 class ObjectFactory;
 class BundleManager;
 class ThreadManager;
 class UserManager;
 class BusManager;
 class DeviceManager;
 class SecurityManager;
 class PersistenceManager;
 class FileSystem;
 class NetworkManager;
 class SystemMonitor;
 class SystemLogger;
 class SessionManager;

 #define _WoshKernel_VERSION				0.8499

 #define _WoshKernel_KEY_State				"State"
 #define _WoshKernel_KEY_LogFile			"LogFile"

 #define _WoshKernel_KEY_BuiltRev			"BuiltRev"
 #define _WoshKernel_KEY_BuiltDate			"BuiltDate"
 #define _WoshKernel_KEY_BuiltPlatform		"BuiltPlatform"

 #define _WoshKernel_KEY_WoshVersionMayor	"WoshVersionMayor"
 #define _WoshKernel_KEY_WoshVersionMinor	"WoshVersionMinor"
 #define _WoshKernel_KEY_WoshCodeName		"WoshCodeName"

 #define _WoshKernel_KEY_InternalThread		"InternalThread"
 #define _WoshKernel_KEY_InternalMutex		"InternalMutex"

 #define _WoshKernel_KEY_StateResumeNext	"WoshKernelStateResumeNext"

 #define _WoshKernel_METHOD_shutdown		"shutdown"
 #define _WoshKernel_METHOD_lsuri			"lsuri"

 #define _WoshKernel_EVENT_StateChanged		"KernelStateChanged"


 #define _WoshKernel_Modules_SIZE			13

class IWoshKernelListener;

class WoshKernel :	public Object,
					public virtual IBusListener,
					public virtual IPropertiesProviderListener,
					protected MethodRunner
 {
	WOSH_CLASSNAME(wosh::WoshKernel)
	WOSH_CLASS_ABSTRACT(false)

	public:
		/// state of the kernel
		enum KERNEL_STATE {
			STATE_UNKNOWN		= 0x00, ///< unknown state, should never happen
			STATE_CREATING		= 0x01,	///< constructor called, kernel is allocating (or retrieving references of) core-modules
			STATE_INITIALIZING	= 0x02,	///< constructor finished, kernel ready to be initialized (init() call)
			STATE_INITIALIZED	= 0x03,	///< core modules have been initialized successfully
			STATE_RUNNING		= 0x04,	///< wosh is running
			STATE_STOPPING		= 0x05,	///< shutdown request was raised, system is switching to STATE_STOPPED
			STATE_STOPPED		= 0x06,	///< STATE_STOPPING succeeded and going to be officially stopped
			STATE_DESTROYING	= 0x07,	///< desctructor called, kernel is destroying modules and internal components
			// 0x08 missing
			STATE_FAILURE		= 0x09	///< something weird happened on previous/current state transition
		 };

	public:
		/**
		 * @brief  Constructor with initializer(s)
		 * @param WoshKernel_name [in] the name of new Kernel (host)
		 * @param settings_default [in] Settings instance to be associated. Otherwise it will be allocated.
		 */
		WoshKernel( const std::string& WoshKernel_name, Settings* settings_default );
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~WoshKernel();


/** @name Kernel control methods
 * @{
 ******************************************************************************/
	public:

		// may re-apply settings
		// INIT modules (allocation order)
		// set state to STATE_INITIALIZED
		WRESULT init();

		// set state to STATE_RUNNING (raising event)
		WRESULT start();

		// reentrant,
		// set state to STATE_STOPPING (raising event)
		// flag stopRequest if enterLoop was called, else set state to STATE_STOPPED (raising event)
		WRESULT shutdown();

		/**
		 * @brief  
		 * @see    WoshKernel::stopRequest 
		 */
		WRESULT enterLoop();

		WRESULT waitStarted();

//@}
/** @name Configuration methods
 * @{
 ******************************************************************************/
	public:
		inline void setListener( IWoshKernelListener* ptr )	{ this->listener = ptr; }

//@}
/** @name Getters and Access to Core-Modules
 * @{
 ******************************************************************************/
	public:
		inline bool isRunning() const 						{ return (this->state == WoshKernel::STATE_RUNNING); }

		inline WoshKernel::KERNEL_STATE getState() const	{ return this->state; }

		inline Settings& settings()							{ return *this->SettingsDefault; }

		inline ObjectFactory& factory() 					{ return *this->Factory; }

		inline BundleManager& bundles() 					{ return *this->Bundles; }
		inline DeviceManager& devices() 					{ return *this->Devices; }
		inline UserManager& users()							{ return *this->Users; }

		inline PersistenceManager& persistence() 			{ return *this->Persistence; }

		inline FileSystem& filesystem()						{ return *this->FS; }

		inline BusManager& busses()							{ return *this->Busses; }
		inline NetworkManager& network()					{ return *this->Network; }

		inline SessionManager& sessions()					{ return *this->Sessions; }

		inline ThreadManager& threads()						{ return *this->Threads; }
		inline SecurityManager& security()					{ return *this->Security; }

		inline SystemMonitor& monitor()						{ return *this->Monitor; }
		inline SystemLogger& logger()						{ return *this->SysLog; }


//@}
/** @name Static Methods (Getters)
 * @{
 ******************************************************************************/
	public:
		static const char* getKernelName();
		static WoshKernel::KERNEL_STATE getKernelState();

		static WoshKernel* getInstance();

		static const char* getStateAsString( WoshKernel::KERNEL_STATE state );
		static KERNEL_STATE getStateFromString( const char* state );

		static WRESULT importInstance( WoshKernel* global_instance );

	//	static std::string getWoshPID();
	//	static WRESULT createWoshPID();
	//	static WRESULT deleteWoshPID();
	//	static int checkWoshPID( const std::string& WoshKernel_name );

//@}
/** @name IPropertiesProviderListener interface
 * @{
 ******************************************************************************/
 	public:
		inline bool readingProperty( Property* , const PropertiesProvider* ) { return true; }
		bool updatingProperty( bool& do_update, const Variant& value_proposed, Property& property_current, const PropertiesProvider* source );
//@}
/** @name IBusListener interface
 * @{
 ******************************************************************************/
 	public:
		void busMessage( const Message& message, const Bus* source );
//@}
/** @name Supported methods
 * @{
 ******************************************************************************/
	private:
		Response* mmDoListURI( const Request* request );

//@}
/** @name Internal methods
 * @{
 ******************************************************************************/
	protected:
		WRESULT setState( WoshKernel::KERNEL_STATE state, bool raise_event = true );
//@}
/** @name Internal modules
 * @{
 ******************************************************************************/
	protected:
		WoshModule** modules;			///< shadow modules' pointer list

		ObjectFactory* Factory;			///< core module managing (dynamic) creation of new (generic) objects

		BundleManager* Bundles;			///< core module managing Bundles
		DeviceManager* Devices;			///< core module managing Devices (as shadow objects)
		ThreadManager* Threads;			///< core module managing Threads
		UserManager* Users;				///< core module managing Users
		SecurityManager* Security;		///< core module managing Security of the Host (system)

		SessionManager* Sessions;		///< core module managing (user) Sessions

		PersistenceManager* Persistence;///< core module managing Database (access, serialization)

		FileSystem* FS;					///< core module managing FileSystem (mappings, virtual->local, shared)

		BusManager* Busses;				///< core module managing Busses (instances and routing)
		NetworkManager* Network;		///< core module managing Networking (WoshHosts, NetworkChannels, NetworkProtocols)

		SystemMonitor* Monitor;			///< core module monitoring the system for issues
		SystemLogger* SysLog;			///< core module offering logging features

//@}
/** @name Internal vars
 * @{
 ******************************************************************************/
	protected:
		mutable LogContext Log;						///< my own logger
		PropertiesProvider Properties;				///< my own properties
		MethodsProvider Methods;					///< my own methods
		BusConnector BusCore;						///< my bus connector to wosh.Bus.Core

		Settings* SettingsDefault;					///< default global settings (acquired on constructor or allocated)

		WoshKernel::KERNEL_STATE state;				///< current kernel state
		bool stopRequest;							///< flag, enabled when a stop request has been activated
		bool loopAcquired;							///< flag, enabled when calling enterLoop()
		IWoshKernelListener* listener;				///< listener reference for callbacks

//@}
	private:
		WoshKernel() { }
		WoshKernel(const WoshKernel&) : Object() { }
		WoshKernel& operator=(const WoshKernel&) { return *this; }


}; // class def



class IWoshKernelListener {
	public:
		// on state-changed.
		// after module notification
		// before raising event
		virtual void kernel_StateChanged( WoshKernel::KERNEL_STATE old_state, WoshKernel::KERNEL_STATE new_state, WoshKernel* kernel ) = 0;

	public:
		virtual ~IWoshKernelListener() { }

}; // class def




/**
 * @class   wosh::WoshKernel_StateChanged
 * @brief   Raised when state of the kernel has changed.
 *
 * Internally, data is stored as wosh::List. Supports also wosh::Variant type.
 *
 * Fields are:
 *  - \c username [Variant::STRING] (always present, first item of the list)
 *  - \c action type (optional, default: new user)
 *
 * Some getters are provided for convenience:
 * \code

 * \endcode
 *
 * @see     wosh::Fact
 * @see     wosh::WoshKernel
 ****************************************************************************
 * @version 0.8.399 $Id: WoshKernel.h 2827 2010-08-02 11:01:48Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
class WoshKernel_StateChanged : public Fact
 {
	WOSH_SERIALIZABLE(wosh::WoshKernel_StateChanged)

	public:
		/**
		 * @brief  Empty constructor.
		 */
		WoshKernel_StateChanged()
			: Fact(_WoshKernel_EVENT_StateChanged) { }
		/**
		 * @brief  Constructor with initializers.
		 * @param new_state [in] new state of the kernel
		 */
		WoshKernel_StateChanged( WoshKernel::KERNEL_STATE new_state );
		/**
		 * @brief  Constructor with initializers.
		 * @param new_state [in] new state of the kernel
		 * @param old_state [in] old (previous) state of the kernel
		 */
		WoshKernel_StateChanged( WoshKernel::KERNEL_STATE new_state, WoshKernel::KERNEL_STATE old_state );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		WoshKernel_StateChanged( const WoshKernel_StateChanged& m )
			: Fact(m) { }
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~WoshKernel_StateChanged() { }

	public:
		/**
		 * @brief   Get state of the kernel
		 * @return  current kernel state (enum)
		 */
		WoshKernel::KERNEL_STATE getState() const;

		WoshKernel::KERNEL_STATE getPreviousState() const;

		const char* getStateAsString() const				{ return WoshKernel::getStateAsString( getState() ); }
		const char* getPreviousStateAsString() const		{ return WoshKernel::getStateAsString( getState() ); }


}; // class def













}; // namespace wosh

#endif //__WOSH_Core_WoshKernel_H__

